import { h } from "vue"
interface Vnode {
  type: string
  tag: string | null
  props: object | null
  children: Array<Vnode> | string
}
enum NodeType {
  Element = 1,
  Text = 3,
}

export const templateTransformNode = (template: string): HTMLElement => {
  const container = document.createElement("div")
  container.innerHTML = template
  return container.firstElementChild as HTMLElement
}

export const nodesTransformVNodes = (node: Node): Vnode => {
  const VNode: Vnode = {} as Vnode
  VNode.tag = node.nodeType == NodeType.Element ? node.nodeName : null
  VNode.props =
    node.nodeType == NodeType.Element ? parseProps(node as HTMLElement) : null
  VNode.type = NodeType[node.nodeType]
  VNode.children =
    node.nodeType == NodeType.Element
      ? ([] as Array<Vnode>)
      : (node.nodeValue as string)
  for (let i = 0; i < node.childNodes.length; i++) {
    typeof VNode.children != "string" &&
      VNode.children.push(nodesTransformVNodes(node.childNodes[i]))
  }
  return VNode
}

const parseProps = (element: HTMLElement): object => {
  let props = {}
  for (let i = 0; i < element.attributes.length; i++) {
    let attr = element.attributes[i]
    props[attr.name] = attr.value
  }
  return props
}

export const VNodesTransformRenderFunction = (
  Vnode: Vnode,
  components: object,
) => {
  const createChildren = (children: Array<Vnode> | string) => {
    const childrenRenderFunctionArray: Array<any> = []
    if (typeof children == "string") {
      childrenRenderFunctionArray.push(children)
      return childrenRenderFunctionArray
    } else {
      children.forEach((item: Vnode) => {
        childrenRenderFunctionArray.push(
          item.type == "Text"
            ? item.children
            : VNodesTransformRenderFunction(item, components),
        )
      })
      return childrenRenderFunctionArray
    }
  }
  //   console.log(Vnode.tag?.toLowerCase())

  //   console.log(components)

  return h(
    components[Vnode.tag?.toLowerCase() as string]
      ? components[Vnode.tag?.toLowerCase() as string]
      : Vnode.tag,
    Vnode.props,
    {
      default: () => createChildren(Vnode.children),
    },
  )
}
